#pragma once

#include "types.h"
#include <cstdint>
#include <time.h>

namespace Trade {


enum DIR_FACTOR_ITEM : uint32_t
{
  DFI_NONE = 0x00000000,
  DFI_G2_BOTH_DIR = 0x00000001,
  DFI_G2_HP_DELTA = 0x00000002,
  DFI_G2_DIR = 0x00000004,
  DFI_WFW_CLS_DIR = 0x00000008,
  DFI_WFW_VSS_DIR = 0x00000010,
  DFI_PDC_CONFUSED = 0x00000020,
  DFI_PDC_CURRENT_OPPOSITE = 0x00000040,
  DFI_PDC_CURRENT_SAMESIDE = 0x00000080,
  DFI_PDC_POSIBLE_OPPOSITE = 0x00000100,
  DFI_PDC_POSIBLE_SAMESIDE = 0x00000200,
  DFI_MID_DIR = 0x000000400,
  DFI_VSS_DIR = 0x000000800,
  DFI_SPP_CLS_DIR = 0x00001000,
  DFI_SPP_VSS_DIR = 0x00002000,
};

struct Incomming
{
  dir_t d_big_reverse = 0;
  bool im_needle = 0;
  bool im_big_needle = 0;
  bool im_big_reverse = 0;
  int64_t idx_rvn_max = 0;
  int64_t idx_rvn_min = 0;
  time_t tm_rvn_max = 0;
  time_t tm_rvn_min = 0;
  int64_t count_win = 0;
  int64_t count_loss = 0;
  price_t rvn_max = 0;
  price_t hp_rvn_max = 0;
  price_t rvn_min = 0;
  price_t hp_rvn_min = 0;
  price_t rvn_total = 0;
  price_t rvn_single = 0;
  price_t hpx_average = 0;
  price_t max_win_rvn = 0;
  price_t max_loss_rvn = 0;

  price_t get_max_rvn_delta() const noexcept;
  void update_revenue(const price_t hp_now,
                      const dir_t dir,
                      const price_t avg_px,
                      const int8_t amount,
                      const time_t tm,
                      const int64_t idx) noexcept;
  price_t max_slope() const noexcept;
  price_t get_amp() const noexcept;
  bool big_needle_changed(const price_t hp_now, const time_t ts) noexcept;
  bool big_reverse_changed(const price_t hp_now, const time_t ts) noexcept;
  void copy(const Incomming* in) noexcept;
  void reset() noexcept;
  price_t try_rvn(const price_t hpx, const dir_t d) const noexcept;
  price_t get_good_for_win(const dir_t d) const noexcept;
  price_t get_stop_loss(const case_t cno) const noexcept;
  price_t get_stop_win(const case_t cno) const noexcept;
  price_t get_loss_rate() const noexcept;
  price_t get_shrink() const noexcept;
  price_t get_rvn_delta() const noexcept;
  dir_t get_dir_rvn_delta(const dir_t md) const noexcept;
};

struct Pricing
{
  static const int LENGTH = 4;
  int amount = 0;
  price_t average = 0;
  price_t price[LENGTH] = { 0 };
  void cal_average() noexcept;
  void push_back(const price_t p) noexcept;
  void clear() noexcept;
  void pop_back() noexcept;
  void push(const price_t p1,
            const price_t p2 = 0,
            const price_t p3 = 0,
            const price_t p4 = 0) noexcept;
  void print(const price_t hp_now) const noexcept;
  Pricing() noexcept;
};

} // namespace Trade